package com.itzg.clipnoter;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.ScrollPaneConstants;
import javax.swing.SpinnerNumberModel;
import javax.swing.Timer;
import javax.swing.border.EmptyBorder;

public class ClipNoterMain extends JFrame {
	private static final int CLIP_WATCH_INTERVAL = 250;
	private static final long serialVersionUID = 1L;
	private Clipboard systemClipboard;
	private Object prevDataObject;
	private File lastDumpFile;
	
	private JSpinner spinner;
	private JTextField resultingFileName;
	private JTextArea textArea;
	private JPopupMenu delimChoice;
	
	private static final String TAB = "\t";
	private static final String COMMA = ",";
	private String delim = TAB;
	private JButton btnDumpCsv;

	public ClipNoterMain() {
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setTitle("Clip Noter");
		
		JPanel panel = new JPanel();
		panel.setBorder(new EmptyBorder(5, 5, 5, 5));
		getContentPane().add(panel, BorderLayout.SOUTH);
		panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
		
		JButton btnNewButton_1 = new JButton("Clear");
		btnNewButton_1.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				clearContent();
			}
		});
		panel.add(btnNewButton_1);
		
		Component horizontalStrut_2 = Box.createHorizontalStrut(20);
		panel.add(horizontalStrut_2);
		
		JLabel lblNewLabel = new JLabel("By");
		panel.add(lblNewLabel);
		
		spinner = new JSpinner();
		spinner.setModel(new SpinnerNumberModel(3, 1, 500, 1));
		panel.add(spinner);
		
		JLabel lblNewLabel_1 = new JLabel("'s");
		panel.add(lblNewLabel_1);
		
		btnDumpCsv = new JButton("Dump CSV");
		btnDumpCsv.setToolTipText("Right-click to choose delimiter");
		btnDumpCsv.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseReleased(MouseEvent e) {
				if (e.isPopupTrigger()) {
					delimChoice.show(btnDumpCsv, 0, 0);
				}
			}
		});
		btnDumpCsv.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				dumpCsv((Integer)spinner.getValue());
			}
		});
		
		Component horizontalStrut = Box.createHorizontalStrut(20);
		panel.add(horizontalStrut);
		panel.add(btnDumpCsv);
		
		resultingFileName = new JTextField();
		resultingFileName.setToolTipText("Click to copy path to clipboard");
		resultingFileName.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				copyDumpFilePath();
			}
		});
		
		Component horizontalStrut_1 = Box.createHorizontalStrut(20);
		panel.add(horizontalStrut_1);
		resultingFileName.setEditable(false);
		resultingFileName.setBorder(null);
		panel.add(resultingFileName);
		resultingFileName.setColumns(20);
		
		Component horizontalGlue = Box.createHorizontalGlue();
		panel.add(horizontalGlue);
		
		JScrollPane scrollPane = new JScrollPane();
		scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
		getContentPane().add(scrollPane, BorderLayout.CENTER);
		
		delimChoice = new JPopupMenu();
		
		ButtonGroup delimButtonGroup = new ButtonGroup();
		
		Action chooseTabAction = new AbstractAction("Tab") {
			private static final long serialVersionUID = 1L;

			@Override
			public void actionPerformed(ActionEvent e) {
				if (delim != TAB) {
					delim = TAB;
					firePropertyChange(Action.SELECTED_KEY, Boolean.FALSE, Boolean.TRUE);
				}
			}
			
			@Override
			public Object getValue(String key) {
				if (key.equals(Action.SELECTED_KEY)) {
					return delim == TAB;
				}
				return super.getValue(key);
			}
		};
		JRadioButtonMenuItem tabChoice = new JRadioButtonMenuItem(chooseTabAction);
		delimButtonGroup.add(tabChoice);
		delimChoice.add(tabChoice);
		
		Action chooseCommaAction = new AbstractAction("Comma") {
			private static final long serialVersionUID = 1L;
			
			@Override
			public void actionPerformed(ActionEvent e) {
				if (delim != COMMA) {
					delim = COMMA;
					firePropertyChange(Action.SELECTED_KEY, Boolean.FALSE, Boolean.TRUE);
				}
			}
			
			@Override
			public Object getValue(String key) {
				if (key.equals(Action.SELECTED_KEY)) {
					return delim == COMMA;
				}
				return super.getValue(key);
			}
		};
		JRadioButtonMenuItem commaChoice = new JRadioButtonMenuItem(chooseCommaAction);
		delimButtonGroup.add(commaChoice);
		delimChoice.add(commaChoice);
		
		textArea = new JTextArea();
		textArea.setEditable(false);
		scrollPane.getViewport().setView(textArea);
		setSize(500, 300);
		
		systemClipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
		new Timer(CLIP_WATCH_INTERVAL, new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				checkClipboardContent();
			}
		}).start();
	}
	
	protected void clearContent() {
		textArea.setText("");
	}

	protected void copyDumpFilePath() {
		if (lastDumpFile != null) {
			// null this out so it will skip the next observation
			prevDataObject = null;
			systemClipboard.setContents(new StringSelection(lastDumpFile.getPath()), null);
			
			// Select the text momentarily so there's a visual cue something happened
			resultingFileName.selectAll();
			Timer deselectTimer = new Timer(500, new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					resultingFileName.select(0, 0);
				}
			});
			deselectTimer.setRepeats(false);
			deselectTimer.start();
		}
	}

	protected void dumpCsv(int value) {
		try {
			lastDumpFile = File.createTempFile("ClipNoter-", ".csv", new File(System.getProperty("user.home")+"/Desktop"));

			PrintWriter writer = new PrintWriter(new FileWriter(lastDumpFile));
			try {
				String[] lines = textArea.getText().split(System.getProperty("line.separator"));
				for (int row = 0; row*value < lines.length; ++row) {
					for (int col = 0; col < value; ++col) {
						if (col != 0) {
							writer.print(delim);
						}
						final int pos = row*value + col;
						if (pos < lines.length) {
							writer.print(lines[pos]);
						}
					}
					writer.println();
				}
			} 
			finally {
				writer.close();
			}
			
			clearContent();
			resultingFileName.setText(lastDumpFile.getPath());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	protected void checkClipboardContent() {
		try {
			Object dataObject = systemClipboard.getData(DataFlavor.stringFlavor);
			if (dataObject instanceof String) {
				if (prevDataObject == null) {
					prevDataObject = dataObject;
				}
				else if (!dataObject.equals(prevDataObject)) {
					textArea.append(dataObject.toString()+System.getProperty("line.separator"));
					prevDataObject = dataObject;
				}
			}
		} catch (UnsupportedFlavorException e) {} 
		catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		new ClipNoterMain().setVisible(true);
	}

}
